/*******************************************************************
 * Copyright (C) yel_hb-USTC, 2012                                
 *                                                                  
 * FILE NAME             :  Vector.cpp                                 
 * PRINCIPAL AUTHOR      :  yel_hb                               
 * MODULE NAME           :  VECTOR                             
 * LANGUAGE              :  C++                                      
 * TARGET ENVIRONMENT    :  windows                                   
 * DATE OF FIRST RELEASE :  2012/12/14                              
 * DESCRIPTION           :  implentation the methods defined in 
 *							dmvector.h, here I used kahanSum to
 *							calculate sum.
 ******************************************************************/

/*
 * Revision log:
 *
 * Created by yel_hb,2012/12/14
 * Modified by yel_hb,2012/12/18
 *
 */

#include <vector>
#include <algorithm>
#include <cmath>
#include <iostream>
#include "dmvector.h"
#include "kahansum.h"
using namespace std;

DMVector::DMVector()
{
	vlist.clear();
}

DMVector::DMVector( int n )
{
	vlist.resize ( n );
}

void DMVector::fill ( double value )
{
	vector<double>::iterator ix;
	for ( ix = vlist.begin(); ix != vlist.end(); ++ix )
	{
		*ix = value;
	}
}

double DMVector::get ( int i ) const
{
	if ( i >= 0 && i < vlist.size())
	{
		return vlist[i];
	}

	return 0;
}


double DMVector::get ( vector<double>::iterator ix ) const
{
	if ( ix != vlist.end() )
	{
		return *ix;
	}

	return 0;
}

void DMVector::set ( int i, double value )
{
	if ( i >= 0 && i < vlist.size())
	{
		vlist[i] = value;
	}
	else
	{
		vlist.push_back ( value );
	}
}

void DMVector::add ( const DMVector& v)
{
	DMVector tmp = v;
	vector<double>::iterator ix;
	
	if ( tmp.size() != vlist.size() )
		return;

	for ( ix = vlist.begin() ; ix != vlist.end(); ++ix )
	{
		*ix += tmp.get( ix );
	}
}

void DMVector::sub ( const DMVector& v)
{
	DMVector tmp = v;
	int size, i;

	if ( tmp.size() != vlist.size() )
		return;

	size = tmp.size();
	for ( i = 0; i < size; ++i )
	{
		set ( i, vlist[i] - tmp.get ( i ));
	}
}

void DMVector::mul ( double k )
{
	vector<double>::iterator ix;
	for ( ix = vlist.begin(); ix != vlist.end(); ++ix )
		*ix *= k;
}

void DMVector::inc_mul ( const DMVector& v, double k )
{
	DMVector tmp = v;
	vector<double>::iterator ix;
	
	if ( tmp.size() != vlist.size() )
		return;

	for ( ix = vlist.begin() ; ix != vlist.end(); ++ix )
	{
		*ix += ( tmp.get( ix ) * k );
	}
}

double DMVector::dot ( const DMVector& v )
{
	double dotsum = 0;
	KahanSum kahan;
	DMVector tmp = v;
	vector<double>::iterator ix;
	if ( tmp.size() != vlist.size() )
		return 0;

	int i = 0;
	kahan.reset();
	for ( ix = vlist.begin() ; ix != vlist.end(); ++ix )
	{
		kahan.add( (*ix) * tmp.get ( i++ ));
	}
	return kahan.get_sum();
}

double DMVector::square_norm ()
{
	vector<double>::iterator ix;
	KahanSum kahan;
	for ( ix = vlist.begin(); ix != vlist.end(); ++ix )
	{
		kahan.add( (*ix) * (*ix) );
	}
	return kahan.get_sum();
}

double DMVector::norm ()
{
	return sqrt ( this->square_norm() );
}

double DMVector::sum ()
{
	vector<double>::iterator ix;
	KahanSum kahan;
	for ( ix = vlist.begin(); ix != vlist.end(); ++ix )
		kahan.add ( *ix );

	return kahan.get_sum();
}

double DMVector::min ()
{
	return *min_element ( vlist.begin(), vlist.end());
}

double DMVector::max ()
{
	return *max_element ( vlist.begin(), vlist.end());
}

int DMVector::size()
{
	return vlist.size();
}

DMVector::~DMVector()
{
	vlist.clear();
}